package cn.cs.controller;

import cn.cs.common.Constants;
import cn.cs.common.Dto;
import cn.cs.common.DtoUtil;
import cn.cs.config.WXPayConfig;
import cn.cs.pojo.Order;
import cn.cs.service.QgWxpayService;
import cn.cs.util.*;
import net.sf.json.JSONArray;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;



@Controller
@RequestMapping("/wxPayment")
public class WxPaymentController {

    private Logger logger = Logger.getLogger(WxPaymentController.class);

    @Resource
    private QgWxpayService qgWxpayService;

    @Resource
    private WXPayConfig wxPayConfig;

    /**
     * 订单微信支付（扫码付）
     * @param orderNo
     * @param response
     * @param request
     * @return
     */
    @RequestMapping(value = "/createqccode/{orderNo}", method = RequestMethod.GET)
    @ResponseBody
    public Dto createQcCode(@PathVariable String orderNo, HttpServletResponse response, HttpServletRequest request) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        Order order = null;
        //定义map类型的变量data，其中存放进行请求统一下单所需要的参数
        HashMap<String, String> data = new HashMap<String, String>();
        HashMap<String, Object> result = new HashMap<String, Object>();
        WXPayRequest wxPayRequest = new WXPayRequest(this.wxPayConfig);
        try {
//            order = qgWxpayService.loadQgOrderByOrderNo(orderNo);
//            if (order == null || order.getStatus() != 0) {
//                return DtoUtil.returnFail("订单状态异常", Constants.WxpayStatus.DDZTYC);
//            }
            data.put("body", "订单支付");
            data.put("out_trade_no", orderNo);
            data.put("device_info", "");
            data.put("total_fee", "1");
            data.put("spbill_create_ip", "169.254.193.209");
            data.put("notify_url", "https://www.zzzsyh.com/api/wxpay/notify");
            Map<String, String> r = wxPayRequest.unifiedorder(data);
            String resultCode = r.get("result_code");
            if (resultCode.equals("SUCCESS")) {
                result.put("goodsId", order.getBookId());
                result.put("amount", order.getAmount());
                result.put("codeUrl", r.get("code_url"));
                return DtoUtil.returnDataSuccess(result);
            } else {
                logger.info(r.get("return_msg"));
                return DtoUtil.returnFail("订单支付异常", Constants.WxpayStatus.DDZFYC);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return DtoUtil.returnFail("订单运行异常", Constants.WxpayStatus.DDYXYC);
        }
    }


    /***
     *
     * 微信支付轮询订单，查看订单是否支付成功
     *
     * @param orderNo
     * @return
     */
    @RequestMapping(value = "/queryorderstatus/{orderNo}", method = RequestMethod.GET)
    @ResponseBody
    public Dto<Order> queryOrderIsSuccess(@PathVariable String orderNo, HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        Order order = null;
        try {
//            order = qgWxpayService.loadQgOrderByOrderNo(orderNo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return DtoUtil.returnDataSuccess(order);
    }

    @RequestMapping(value = "/p/notify", method = RequestMethod.POST)
    @ResponseBody
    public String paymentCallBack(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", "*");
        WXPayRequest wxPayRequest = new WXPayRequest(this.wxPayConfig);
        Map<String, String> result = new HashMap<String, String>();
        Map<String, String> params = null;
        String returnxml = "";
            InputStream inputStream;
            StringBuffer sb = new StringBuffer();
            //以字节流的形式读取request中的数据
            inputStream = request.getInputStream();
            String s;
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            while ((s = in.readLine()) != null) {
                sb.append(s);
            }
            in.close();
            inputStream.close();
            params = WXPayUtil.xmlToMap(sb.toString());
            logger.info("1.notify-params>>>>>>>>>>>:" + params);

            String returnCode = params.get("return_code");
            logger.info("3.returnCode:" + returnCode);
            if (returnCode.equals("SUCCESS")) {
                //判断签名是否正确
                boolean flag = wxPayRequest.isResponseSignatureValid(params);
                logger.info("2.notify-flag:" + flag);
                if (flag) {
                    //获取微信订单号
                    String transactionId = params.get("transaction_id");
                    //获取商户订单号
                    String outTradeNo = params.get("out_trade_no");
                    //附加信息原路返回   recharge:充值 order:订单
                    String attach = params.get("attach");
                    logger.info("aaa====================================" + transactionId);
                    logger.info("bbb====================================" + outTradeNo);
                    logger.info("ccc====================================" + attach);
                    Map<String, Object> map = qgWxpayService.processed(outTradeNo, attach);//获取充值订单，或者维修订单
                    logger.info("map====================================" + map);
                    //pay_status 支付状态 1未支付 2支付成功 0支付失败（原来）
                    //改为 当attach为recharge（充值） 是 同上  当attach为order（维修订单） 时2未支付 3支付成功
                    //当attach为test_report 检测费时   是否支付检测费，0未支付，1已支付
                    if (("1".equals(map.get("pay_status")) && "recharge".equals(attach)) || ("2".equals(map.get("pay_status")) && "order".equals(attach))
                            || ("0".equals(map.get("pay_status")) && "test_report".equals(attach))) {
                        qgWxpayService.insertTrade(outTradeNo, transactionId, map.get("userId").toString(), map.get("amount").toString(), "1");
                        logger.info("修改订单状态====================================");
                        qgWxpayService.updateOrderStatus(map, attach);
                    }

                    logger.info("4.订单：" + outTradeNo + " 交易完成" + ">>>" + transactionId);
                } else {
                    result.put("return_code", "FAIL");
                    result.put("return_msg", "签名失败");
                    logger.info("签名验证失败>>>>>>>>>>>>");
                }
            } else {
                result.put("return_code", "FAIL");
                result.put("return_msg", "支付失败");
                logger.info("");
            }


            returnxml = WXPayUtil.mapToXml(result);
        return returnxml;
    }

    /**
     * JSAPI支付
     */
    @ResponseBody
    @RequestMapping(value = "/p/wxPay", method = RequestMethod.GET)
    public List<Map<String, Object>> wxPay(String totalfee, String openid, String attach, String orderId, HttpServletResponse response, HttpServletRequest request) throws IOException {
        response.setHeader("Access-Control-Allow-Origin", "*");
        List<Map<String, Object>> commlist = new ArrayList<Map<String, Object>>();
        Map<String, Object> resultmap = new HashMap<String, Object>();
        //微信支付jsApi
        System.out.println(openid);
        WxPayDto tpWxPay = new WxPayDto();
        tpWxPay.setOpenId(openid);
        if ("recharge".equals(attach)) {
            tpWxPay.setBody("充值");
        } else if ("order".equals(attach)) {
            tpWxPay.setBody("维修费");
        } else if ("test_report".equals(attach)) {
            tpWxPay.setBody("检测费");
        } else {
            tpWxPay.setBody("其他");
        }
        tpWxPay.setOrderId(orderId);
        tpWxPay.setSpbillCreateIp("127.0.0.1");
        tpWxPay.setTotalFee(totalfee);
        tpWxPay.setAttach(attach);

        String returnresult = getPackage(tpWxPay);
        System.out.println(returnresult);
        String[] resultarray = returnresult.split(",");
        for (String item : resultarray) {
            String[] temp = item.split(":");
            System.out.println("item" + item);
            System.out.println("temp[0]" + temp[0] + "temp[1]" + temp[1]);
            temp[0] = temp[0].replaceAll("\"", "");
            temp[1] = temp[1].replaceAll("\"", "");
            resultmap.put(temp[0], temp[1]);
        }
        commlist.add(resultmap);
        JSONArray json = JSONArray.fromObject(commlist);
        response.reset();
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        ServletOutputStream out = response.getOutputStream();
        //out.print(callback + "(" + json + ")");

        System.out.println("json**********" + json + "***************");
//        System.out.println("callback"+callback+"*********************after");
        return json;
    }

    /**
     * 获取微信扫码支付二维码连接
     */
    public String getCodeurl(WxPayDto tpWxPayDto) {

        // 1 参数
        // 订单号
        String orderId = tpWxPayDto.getOrderId();
        // 附加数据 原样返回
        String attach = "";
        // 总金额以分为单位，不带小数点
        String totalFee = getMoney(tpWxPayDto.getTotalFee());

        // 订单生成的机器 IP
        String spbill_create_ip = tpWxPayDto.getSpbillCreateIp();
        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        String notify_url = "http://www.zzzsyh.com/cs_pay/wxpay/notify";
        String trade_type = "NATIVE";

        // 商户号
        String mch_id = wxPayConfig.getMchID();
        // 随机字符串
        String nonce_str = getNonceStr();

        // 商品描述根据情况修改
        String body = tpWxPayDto.getBody();

        // 商户订单号
        String out_trade_no = orderId;

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", wxPayConfig.getAppID());
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("attach", attach);
        packageParams.put("out_trade_no", out_trade_no);

        // 这里写的金额为1 分到时修改
        packageParams.put("total_fee", totalFee);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);

        packageParams.put("trade_type", trade_type);

        RequestHandler reqHandler = new RequestHandler(null, null);
        reqHandler.init(wxPayConfig.getAppID(), wxPayConfig.getAppSecret(), wxPayConfig.getKey());

        String sign = reqHandler.createSign(packageParams);
        String xml = "<xml>" + "<appid>" + wxPayConfig.getAppID() + "</appid>" + "<mch_id>"
                + mch_id + "</mch_id>" + "<nonce_str>" + nonce_str
                + "</nonce_str>" + "<sign>" + sign + "</sign>"
                + "<body><![CDATA[" + body + "]]></body>"
                + "<out_trade_no>" + out_trade_no
                + "</out_trade_no>" + "<attach>" + attach + "</attach>"
                + "<total_fee>" + totalFee + "</total_fee>"
                + "<spbill_create_ip>" + spbill_create_ip
                + "</spbill_create_ip>" + "<notify_url>" + notify_url
                + "</notify_url>" + "<trade_type>" + trade_type
                + "</trade_type>" + "</xml>";
        String code_url = "";
        String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";


        code_url = new GetWxOrderno().getCodeUrl(createOrderURL, xml);
        System.out.println(code_url + "<<<<>>>>>>");
        return code_url;
    }


    /**
     * 获取请求预支付id报文
     *
     * @return
     */
    @SuppressWarnings("static-access")
    public String getPackage(WxPayDto tpWxPayDto) {

        String openId = tpWxPayDto.getOpenId();
        // 1 参数
        // 订单号
        String orderId = tpWxPayDto.getOrderId();
        // 附加数据 原样返回
        String attach = tpWxPayDto.getAttach();
        // 总金额以分为单位，不带小数点
        String totalFee = getMoney(tpWxPayDto.getTotalFee());

        // 订单生成的机器 IP
        String spbill_create_ip = tpWxPayDto.getSpbillCreateIp();
        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
//        String notify_url = "http://www.zzzsyh.com/cs_pay/wxpay/notify";
        String trade_type = "JSAPI";

        // ---必须参数
        // 商户号
        String mch_id = wxPayConfig.getMchID();
        // 随机字符串
        String nonce_str = getNonceStr();

        // 商品描述根据情况修改
        String body = tpWxPayDto.getBody();

        // 商户订单号
        String out_trade_no = orderId;

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", wxPayConfig.getAppID());
        packageParams.put("attach", attach);
        packageParams.put("body", body);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
//        packageParams.put("notify_url", "http://n239v16088.qicp.vip/cs_pay/wxpay/notify");
        packageParams.put("notify_url", wxPayConfig.getNotifyUrl());
        packageParams.put("openid", openId);
        packageParams.put("out_trade_no", out_trade_no);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("total_fee", totalFee);
        packageParams.put("trade_type", trade_type);


        RequestHandler reqHandler = new RequestHandler(null, null);
        reqHandler.init(wxPayConfig.getAppID(), wxPayConfig.getAppSecret(), wxPayConfig.getKey());

        String sign = reqHandler.createSign(packageParams);
        System.out.println("第一次签名------------------------------" + sign);
        String xml = "<xml>" + "<appid>" + wxPayConfig.getAppID() + "</appid>" + "<mch_id>"
                + mch_id + "</mch_id>" + "<nonce_str>" + nonce_str
                + "</nonce_str>" + "<sign>" + sign + "</sign>"
                + "<body><![CDATA[" + body + "]]></body>"
                + "<out_trade_no>" + out_trade_no
                + "</out_trade_no>" + "<attach>" + attach + "</attach>"
                + "<total_fee>" + totalFee + "</total_fee>"
                + "<spbill_create_ip>" + spbill_create_ip
                + "</spbill_create_ip>" + "<notify_url>" + wxPayConfig.getNotifyUrl()
                + "</notify_url>" + "<trade_type>" + trade_type
                + "</trade_type>" + "<openid>" + openId + "</openid>"
                + "</xml>";
        String prepay_id = "";
        String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";


        prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);

        System.out.println("获取到的预支付ID：" + prepay_id);


        //获取prepay_id后，拼接最后请求支付所需要的package

        SortedMap<String, String> finalpackage = new TreeMap<String, String>();
        String timestamp = Sha1Util.getTimeStamp();
        String packages = "prepay_id=" + prepay_id;
        finalpackage.put("appId", wxPayConfig.getAppID());
        finalpackage.put("timeStamp", timestamp);
        finalpackage.put("nonceStr", nonce_str);
        finalpackage.put("package", packages);
        finalpackage.put("signType", "MD5");
        //要签名
        String finalsign = reqHandler.createSign(finalpackage);
        System.out.println("第二次签名------------------------------" + finalsign);
        String finaPackage = "\"appId\":\"" + wxPayConfig.getAppID() + "\",\"timeStamp\":\"" + timestamp
                + "\",\"nonceStr\":\"" + nonce_str + "\",\"package\":\""
                + packages + "\",\"signType\" : \"MD5" + "\",\"paySign\":\""
                + finalsign + "\"";

        System.out.println("V3 jsApi package:" + finaPackage);
        return finaPackage;
    }

    /**
     * 获取随机字符串
     *
     * @return
     */
    public static String getNonceStr() {
        // 随机数
        String currTime = TenpayUtil.getCurrTime();
        // 8位日期
        String strTime = currTime.substring(8, currTime.length());
        // 四位随机数
        String strRandom = TenpayUtil.buildRandom(4) + "";
        // 10位序列号,可以自行调整。
        return strTime + strRandom;
    }

    /**
     * 元转换成分
     *
     * @param amount
     * @return
     */
    public static String getMoney(String amount) {
        if (amount == null) {
            return "";
        }
        // 金额转化为分为单位
        String currency = amount.replaceAll("\\$|\\￥|\\,", "");  //处理包含, ￥ 或者$的金额
        int index = currency.indexOf(".");
        int length = currency.length();
        Long amLong = 0l;
        if (index == -1) {
            amLong = Long.valueOf(currency + "00");
        } else if (length - index >= 3) {
            amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
        } else if (length - index == 2) {
            amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
        } else {
            amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
        }
        return amLong.toString();
    }
}
